/**
 * Created by oneminute on 2014/5/5.
 */

var logger = require("./logger");
var config = require("../../config/config");
var uuid = require("node-uuid");
var moment = require("moment");
var lz = require("./modules")();
var path = require("path");
var fs = require("fs");
var ursa = require("ursa");
var urlencode = require("urlencode");

var privateKey = ursa.createPrivateKey(fs.readFileSync(__dirname + "/../../config/lz.pem"));
var publicKey = ursa.createPublicKey(fs.readFileSync(__dirname + "/../../config/iwant.pub"));

exports.getSubList = function (_page, _srcArray, _callback) {
    logger.debug("utils:getSubList: ", _page);
    var retItems = [];
    var start, end, isEnd = true;
    if (_srcArray) {
        logger.debug("utils:getSubList: ", _srcArray.length);
        if (_page >= _srcArray.length) {
            start = _srcArray.length;
            end = _srcArray.length;
            isEnd = true;
        } else {
            start = _page;
            end = start + config.webServer.page;
            if (end >= _srcArray.length) {
                end = _srcArray.length;
                isEnd = true;
            } else {
                isEnd = false;
            }
        }
        logger.debug("utils:getSubList: start=%s, end=%s, isEnd=%s", start, end, isEnd);
        retItems = _srcArray.slice(start, end);
        //logger.debug("utils:getSubList: ", _srcArray);
        _callback(retItems, isEnd);
    } else {
        _callback([], true);
    }
};

exports.getExpireTime = function (_delay) {
    if (!_delay) {
        _delay = config.db.arango.expire;
    }
    var date = new Date();
    date.setSeconds(date.getSeconds() + _delay);
    return moment(date).format(lz.Config.datetimeFormatLong);
};

/**
 * 获取一个UUID。
 *
 * @param _prefix 可以给出uuid的前缀。
 * @returns {*|XML|string|void}
 */
exports.getUUID = function (_prefix) {
    var val = uuid.v1().replace(/-/g, "");
    if (_prefix) {
        val = _prefix + val;
    }
    return val;
};

exports.getRandName = function (_prefix) {
    var id = exports.getUUID();
    var s0 = id.substring(0, 8);
    var s1 = id.substring(8, 16);
    var s2 = id.substring(16, 24);
    var s3 = id.substring(24, 32);
    //lz.Logger.debug(id);
    //lz.Logger.debug("%s%s%s%s", s0, s1, s2, s3);
    var n0 = parseInt(s0, 16);
    var n1 = parseInt(s1, 16);
    var n2 = parseInt(s2, 16);
    var n3 = parseInt(s3, 16);
    //lz.Logger.debug(n0);
    //lz.Logger.debug(n1);
    //lz.Logger.debug(n2);
    //lz.Logger.debug(n3);
    //lz.Logger.debug("%s%s%s%s", n0.toString(16), n1.toString(16), n2.toString(16), n3.toString(16));
    var hh = Math.abs(n0 ^ n3);
    var hl = Math.abs(n1 ^ n2);
    var value = hh.toString(16) + hl.toString(16);
    //lz.Logger.debug(value);
    value = value.substring(0, 14);
    if (_prefix) {
        value = _prefix + value;
    }
    return value;
};

exports.copyObj = function (_from, _to) {
    if (_from) {
        for (var p in _to) {
            if (_from[p] != undefined || _from[p] != null)
                _to[p] = _from[p];
        }
    }
};

exports.endResponse = function (_res, _user) {
    if (!_res.result)
        _res.result = {};
    _res.result.uid = user.id;
    logger.debug("response: ", _res.result);
    _res.send(_res.result);
};

exports.calculateLocation = function (_oriLoc, _distance, _radian) {
    var lon = _oriLoc.lon / 180 * Math.PI;
    var lat = _oriLoc.lat / 180 * Math.PI;
    var e1 = 1 - Math.cos(_distance / this.earthRadius);
    var sinTheta = Math.sin(_radian);
    var cosLat = Math.cos(lat);
    var cos2Lat = cosLat * cosLat;
    var sinLat = Math.sin(lat);
    var sin2Lat = sinLat * sinLat;
    var newLoc = {};
    newLoc.lon = Math.acos((cos2Lat - e1 - e1 * sinTheta * sinLat) / (cosLat * Math.sqrt(cos2Lat - 2 * e1 * sinTheta - 2 * Math.sqrt(2 * e1) * sinTheta * sinLat))) + lon;
    newLoc.lat = Math.asin(sinTheta * Math.sqrt(2 * e1) + sinLat);
    newLoc.lon = newLoc.lon / Math.PI * 180;
    newLoc.lat = newLoc.lat / Math.PI * 180;
    return newLoc;
};

exports.calculateLocationApproximate = function (_oriLoc, _distance, _radian) {
    var lon = _oriLoc.lon / 180 * Math.PI;
    var lat = _oriLoc.lat / 180 * Math.PI;
    var meterLon = 1 / (this.earthRadius * Math.cos(lon));
    var meterLat = 1 / (this.earthRadius);
    var newLoc = {};
    newLoc.lon = _distance * meterLon * Math.cos(_radian) + lon;
    newLoc.lat = _distance * meterLat * Math.sin(_radian) + lat;
    newLoc.lon = newLoc.lon / Math.PI * 180;
    newLoc.lat = newLoc.lat / Math.PI * 180;
    return newLoc;
};

exports.earthRadius = 6378137;

exports.getDefaultProperty = function (_name, _data) {
    return {
        set: function (_value) {
            _data[_name] = _value;
        },
        get: function () {
            return _data[_name];
        },
        enumerable: true
    }
};

exports.getAppVersion = function (_device, _callback) {
    var filepath = path.normalize(path.join(__dirname, '../../public/apps', _device, 'version.json'));
    logger.debug('/version: 版本文件路径: ', filepath);
    fs.readFile(filepath, { encoding: 'utf-8'}, function (_err, _data) {
        logger.debug('/version:readfile: ', _data);
        if (_err) {
            _callback(_err);
        } else {
            var info = JSON.parse(_data);
            info.filename = "woyao" + info.version + ".apk";
            info.url = '/apps/' + _device + '/' + info.version + '/' + info.filename;
            info.device = _device;
            _callback(_err, info);
        }
    });
};

exports.saveApp = function (_info, _callback) {
    logger.debug("utils:saveApp: invoke.");
    // 创建保存路径字符串
    var fileName = "woyao" + _info.version + ".apk";
    var appDir = path.normalize(path.join(__dirname, '../../public/apps/', _info.device, _info.version));
    var appPath = path.normalize(path.join(appDir, fileName));
    var versionFile = path.normalize(path.join(__dirname, '../../public/apps/', _info.device, 'version.json'));
    logger.info("  appDir: %s\n  appPath: %s\n  versionFile: %s", appDir, appPath, versionFile);

    // 更新version.json文件
    function updateVersionFile() {
        delete _info.file;
        fs.writeFile(versionFile, JSON.stringify(_info, null, 4), _callback);
    }

    // 检查路径是否存在
    fs.exists(appPath, function (_exists) {
        if (_exists) {
            fs.createReadStream(_info.file.path).pipe(fs.createWriteStream(appPath));
            updateVersionFile();
        } else {
            // 创建保存路径
            fs.mkdir(appDir, function (_err) {
                logger.info(_err);
                fs.createReadStream(_info.file.path).pipe(fs.createWriteStream(appPath));
                updateVersionFile();
            });
        }
    });

};

exports.decrypt = function (_data, _urlEncoded) {
    lz.Logger.debug("utils:decrypt: 调用.", _data);
    if (_urlEncoded) {
        _data = urlencode.decode(_data);
    }
    var decryptedData = privateKey.decrypt(_data, "base64", 'utf8', ursa.RSA_PKCS1_PADDING);
    lz.Logger.debug("解码: ", decryptedData);
    return decryptedData;
};

exports.encrypt = function (_data) {
    lz.Logger.debug("utils:encrypt: 调用.", _data);
    var encryptedData = "";
    try {
        encryptedData = publicKey.encrypt(_data, undefined, "base64", ursa.RSA_PKCS1_PADDING);
    } catch (e) {
        lz.Logger.error(e.stack);
    }
    return encryptedData;
};
